using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class TimePickerScroller : MonoBehaviour, IEndDragHandler
{
    public ScrollRect scrollRect;
    public RectTransform content; // content under viewport (通常由 Editor 脚本设定)
    public GameObject timeItemPrefab; // TimeItem prefab (Text + Button)
    public int maxValue = 23; // hour 0~23 or minute 0~59
    public int step = 1; // step size (e.g. 1 or 5)
    public float itemHeight = 40f;
    public bool twoDigits = true;
    public bool isHour = true;
    public DateTimePicker parentPicker;

    // 如果 >0 则使用此覆盖的 padding 数量；否则会根据 viewportHeight/itemHeight 自动计算
    public int paddingCountOverride = 0;

    // 视觉相关（可在 Inspector 调整）
    public Color normalTextColor = Color.black;
    public Color selectedTextColor = Color.white;
    public Color normalBackgroundColor = new Color(0f, 0f, 0f, 0f);
    public Color selectedBackgroundColor = new Color(0.26f, 0.59f, 1f, 1f);
    public int selectedFontSizeOffset = 0; // 可选：选中项相对原字体增大多少

    int realItemCount;    // 实际可选项数量 (例如 24 or 60)
    int totalItemCount;   // 包括上下 padding 的总项数
    int paddingTop = 0;   // 顶部 padding 数量
    Coroutine snapCoroutine;

    void Start()
    {
        if (scrollRect != null && content == null) content = scrollRect.content;

        // 尝试确保 viewport 指定
        if (scrollRect != null && scrollRect.viewport == null)
        {
            var vp = scrollRect.transform.Find("Viewport");
            if (vp != null) scrollRect.viewport = vp.GetComponent<RectTransform>();
        }

        Populate();
        int start = isHour ? System.DateTime.Now.Hour : System.DateTime.Now.Minute;
        ScrollToIndex(start, false);

        // 更新视觉（初始）
        UpdateSelectionVisuals();
    }

    void Populate()
    {
        if (content == null || timeItemPrefab == null) return;

        // 清空旧项
        for (int i = content.childCount - 1; i >= 0; i--) DestroyImmediate(content.GetChild(i).gameObject);

        realItemCount = (maxValue / step) + 1;

        // 计算 padding 数量
        float viewportHeight = 0f;
        if (scrollRect != null && scrollRect.viewport != null) viewportHeight = scrollRect.viewport.rect.height;
        else
        {
            var srRt = scrollRect != null ? scrollRect.GetComponent<RectTransform>() : null;
            if (srRt != null) viewportHeight = srRt.rect.height;
        }
        if (viewportHeight <= 0f) viewportHeight = itemHeight * 3f; // fallback

        int autoPad = Mathf.CeilToInt(viewportHeight / itemHeight);
        int pad = paddingCountOverride > 0 ? paddingCountOverride : autoPad;
        paddingTop = pad;

        // 创建顶部 padding（不可见） 
        for (int i = 0; i < pad; i++)
        {
            var go = Instantiate(timeItemPrefab, content);
            MakeItemInvisible(go);
            SetItemHeight(go, itemHeight);
        }

        // 创建真实项
        for (int i = 0; i < realItemCount; i++)
        {
            int value = i * step;
            var go = Instantiate(timeItemPrefab, content);
            var label = go.GetComponentInChildren<Text>();
            if (label) label.text = twoDigits ? value.ToString("D2") : value.ToString();
            var btn = go.GetComponent<Button>();
            if (btn != null)
            {
                btn.onClick.RemoveAllListeners();
                btn.onClick.AddListener(() => OnItemClicked(value));
            }
            SetItemHeight(go, itemHeight);
            // ensure visible
            if (label) label.enabled = true;
            var img = go.GetComponent<Image>();
            if (img != null) img.color = normalBackgroundColor;
            if (label != null) label.color = normalTextColor;
        }

        // 底部 padding（不可见）
        for (int i = 0; i < pad; i++)
        {
            var go = Instantiate(timeItemPrefab, content);
            MakeItemInvisible(go);
            SetItemHeight(go, itemHeight);
        }

        totalItemCount = content.childCount;

        // 更新 content 高度（content.anchor/pivot 假定为上对齐）
        Vector2 s = content.sizeDelta;
        content.sizeDelta = new Vector2(s.x, totalItemCount * itemHeight);

        // 保证 content anchoredPosition 在合法范围内
        ClampContentPosition();

        // 更新视觉
        UpdateSelectionVisuals();
    }

    void SetItemHeight(GameObject go, float height)
    {
        var rt = go.GetComponent<RectTransform>();
        if (rt != null) rt.sizeDelta = new Vector2(rt.sizeDelta.x, height);
    }

    void MakeItemInvisible(GameObject go)
    {
        // 隐藏文本并禁用按钮，同时保持 RectTransform 大小，用作占位
        var label = go.GetComponentInChildren<Text>();
        if (label) { label.text = ""; label.enabled = false; }

        var btn = go.GetComponent<Button>();
        if (btn) btn.interactable = false;

        var img = go.GetComponent<Image>();
        if (img) img.color = new Color(0f, 0f, 0f, 0f);
    }

    void OnItemClicked(int value)
    {
        ScrollToIndex(value, true);
        ApplyValue(value);
        // 视觉将在 SmoothScrollTo 完成后更新；如果需要立刻高亮，可调用 UpdateSelectionVisuals() 但 smoother UX is to wait
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (content == null || scrollRect == null) return;

        // 使用已 clamp 的 Y 来计算索引
        float clampedY = GetClampedContentY(content.anchoredPosition.y);
        int idx = Mathf.RoundToInt(clampedY / itemHeight);
        // 转换成真实索引（减去顶部 padding）
        int realIdx = Mathf.Clamp(idx - paddingTop, 0, realItemCount - 1);
        int val = realIdx * step;
        ScrollToIndex(val, true);
        ApplyValue(val);
    }

    public void ScrollToIndex(int value, bool smooth)
    {
        if (content == null) return;

        int realIdx = Mathf.Clamp(Mathf.RoundToInt((float)value / step), 0, realItemCount - 1);
        int idx = realIdx + paddingTop; // 实际在 content 中的索引（含顶部 padding）
        float targetY = idx * itemHeight;
        targetY = GetClampedContentY(targetY);

        if (snapCoroutine != null) StopCoroutine(snapCoroutine);
        if (smooth)
            snapCoroutine = StartCoroutine(SmoothScrollTo(targetY));
        else
        {
            content.anchoredPosition = new Vector2(content.anchoredPosition.x, targetY);
            UpdateSelectionVisuals();
        }
    }

    IEnumerator SmoothScrollTo(float targetY)
    {
        if (scrollRect) scrollRect.velocity = Vector2.zero;
        float duration = 0.18f;
        float t = 0f;
        float startY = content.anchoredPosition.y;
        targetY = GetClampedContentY(targetY);

        while (t < duration)
        {
            t += Time.unscaledDeltaTime;
            float p = Mathf.SmoothStep(0f, 1f, t / duration);
            float y = Mathf.Lerp(startY, targetY, p);
            content.anchoredPosition = new Vector2(content.anchoredPosition.x, y);
            yield return null;
        }
        content.anchoredPosition = new Vector2(content.anchoredPosition.x, targetY);

        // 平滑滚动结束后更新视觉并确保同步值
        UpdateSelectionVisuals();
    }

    // clamp a content Y to the valid scrollable range [0, maxY]
    float GetClampedContentY(float y)
    {
        float maxY = GetMaxScrollY();
        return Mathf.Clamp(y, 0f, maxY);
    }

    float GetMaxScrollY()
    {
        if (content == null) return 0f;
        float contentHeight = content.rect.height;
        float viewportHeight = 0f;
        if (scrollRect != null && scrollRect.viewport != null) viewportHeight = scrollRect.viewport.rect.height;
        else
        {
            var srRt = scrollRect != null ? scrollRect.GetComponent<RectTransform>() : null;
            if (srRt != null) viewportHeight = srRt.rect.height;
        }
        float maxY = Mathf.Max(0f, contentHeight - viewportHeight);
        return maxY;
    }

    void ClampContentPosition()
    {
        if (content == null) return;
        float y = content.anchoredPosition.y;
        float clamped = GetClampedContentY(y);
        if (!Mathf.Approximately(y, clamped))
            content.anchoredPosition = new Vector2(content.anchoredPosition.x, clamped);
    }

    // 将此方法改为 public，以便外部（例如 DateTimePicker）在程序性更改时强制刷新视觉
    public void UpdateSelectionVisuals()
    {
        if (content == null) return;

        // 计算当前被对齐在顶部（可选的“选中位置”）的真实索引
        float clampedY = GetClampedContentY(content.anchoredPosition.y);
        int idx = Mathf.RoundToInt(clampedY / itemHeight);
        int realIdx = Mathf.Clamp(idx - paddingTop, 0, Mathf.Max(0, realItemCount - 1));

        for (int i = 0; i < content.childCount; i++)
        {
            var child = content.GetChild(i);
            int childRealIdx = i - paddingTop;

            var txt = child.GetComponentInChildren<Text>();
            var img = child.GetComponent<Image>();

            bool isReal = childRealIdx >= 0 && childRealIdx < realItemCount;
            if (!isReal)
            {
                // padding: ensure invisible / neutral
                if (txt != null) txt.enabled = false;
                if (img != null) img.color = normalBackgroundColor;
                continue;
            }

            // visible item
            if (txt != null) txt.enabled = true;

            bool isSelected = (childRealIdx == realIdx);

            if (txt != null)
            {
                txt.color = isSelected ? selectedTextColor : normalTextColor;
                // 字体放大/恢复（若需要）
                if (selectedFontSizeOffset != 0)
                {
                    txt.fontSize = Mathf.Max(1, txt.fontSize + (isSelected ? selectedFontSizeOffset : 0));
                    // NOTE: fontSize 增加会累加，确保 prefab 字体在初始时是你期望的大小，或进一步缓存原始值以避免重复叠加。
                }
            }

            if (img != null)
            {
                img.color = isSelected ? selectedBackgroundColor : normalBackgroundColor;
            }
        }
    }

    void ApplyValue(int v)
    {
        if (parentPicker == null) return;
        var cal = parentPicker.calendar;
        if (cal == null) return;
        if (isHour) cal.SetTime(v, cal.GetSelectedDateTime().Minute);
        else cal.SetTime(cal.GetSelectedDateTime().Hour, v);

        // 同步顶部文字
        parentPicker?.UpdateTopText();
    }
}